package com.zmzncs.lmtc.module.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zmzncs.lmtc.common.config.ClientConfig;
import com.zmzncs.lmtc.common.pojo.Rest;
import com.zmzncs.lmtc.common.pojo.tengda.*;
import com.zmzncs.lmtc.common.util.BolianUtil;
import com.zmzncs.lmtc.common.util.DateTimeUtil;
import com.zmzncs.lmtc.common.util.RestUtil;
import com.zmzncs.lmtc.common.util.TengdaUtil;
import com.zmzncs.lmtc.module.customer.dao.CarDao;
import com.zmzncs.lmtc.module.customer.pojo.car.CarDTO;
import com.zmzncs.lmtc.module.order.dao.OrderInfoDao;
import com.zmzncs.lmtc.module.order.dao.OrderTradeRecordDao;
import com.zmzncs.lmtc.module.order.pojo.orderInfo.OrderInfo;
import com.zmzncs.lmtc.module.order.pojo.orderInfo.OrderInfoDTO;
import com.zmzncs.lmtc.module.order.service.OrderInfoService;
import com.zmzncs.lmtc.module.park.dao.ParkInfoDao;
import com.zmzncs.lmtc.module.park.pojo.parkinfo.ParkInfoDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

import java.math.BigDecimal;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * <p>
 * 订单
 * </p>
 *
 * @author
 * @since 2020-09-01
 */
@Slf4j
@Service
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoDao, OrderInfo> implements OrderInfoService {

    @Autowired
    OrderInfoDao orderInfoDao;
    @Autowired
    OrderTradeRecordDao orderTradeRecordDao;
    @Autowired
    private ClientConfig clientConfig;
    @Autowired
    private CarDao carDao;
    @Autowired
    private ParkInfoDao parkInfoDao;
    @Autowired
    private TengdaUtil tengdaUtil;

    @Autowired
    HttpServletRequest request;

    @Value("${pay-test}")
    boolean payTest;

    public static List<TengdaForm> tengdaOrderFormList = new ArrayList<>();

    /**
     * 车辆进场通知
     */
    @Override
    @Transactional
    public void carInPark(TengdaForm form) throws InterruptedException {
        log.info("进场通知【{}】", form);
        CarInForm carInForm = JSONObject.toJavaObject(form.getDataItems().get(0), CarInForm.class);
        log.info("进场通知-业务数据【{}】", carInForm);

        //  入场时间
        Long enterTime = DateTimeUtil.stringToDate(carInForm.getEnterTime()).getTime() / 1000;

        //  车牌
        CarDTO carDTO = carDao.getCustCarByCarNumber(carInForm.getPlateNumber());
        if(carDTO != null) {
            //  上传进场记录到泊链
            Boolean addFlag = BolianUtil.addInParkOrder(form.getParkCode(), carInForm.getPlateNumber(), enterTime, carInForm.getRecordNo(), carInForm.getRemainParkNum());
            if(addFlag){
                Thread.sleep(8 * 1000);

                //  根据订单号查询订单
                OrderInfoDTO orderInfoDTO = orderInfoDao.getByOrderCode(carInForm.getRecordNo());
                //  8秒后如果还没查询到订单，则手动入库
                if(orderInfoDTO == null){
                    BolianUtil.carInPark(carInForm.getRecordNo(), form.getParkCode(), carInForm.getPlateNumber(), enterTime);
                }
            }
        } else {
            log.info("车牌【{}】非会员车，不上传泊链", carInForm.getPlateNumber());

            //  非会员订单，则手动出场
            BolianUtil.carInPark(carInForm.getRecordNo(), form.getParkCode(), carInForm.getPlateNumber(), enterTime);
        }
    }

    /**
     * 实时订单
     */
    @Override
    public void queryCurrOrder(TengdaForm form) {
        log.info("实时订单通知【{}】", form);
        CurrFeeForm currFeeForm = new CurrFeeForm();
        if(form.getCode().equals(1)){
            currFeeForm = JSONObject.toJavaObject(form.getDataItems().get(0), CurrFeeForm.class);
            log.info("实时订单-业务数据【{}】", currFeeForm);
        }

//        form.setDataItems(Arrays.asList(JSON.parseObject(currFeeForm.toString())));
        tengdaOrderFormList.add(form);
        log.info("实时订单-缓存业务数据【{}】", tengdaOrderFormList);
    }

    /**
     * 停车订单支付通知
     */
    @Override
    public void payParkingFeeOrder(TengdaForm form) throws InterruptedException {
        log.info("停车订单支付通知：{}", form);

        //  缓存中查询响应数据
        for (int i=0; i<10; i++) {
            Thread.sleep(500);

            //  如果uuid相同，则响应数据
            Optional<TengdaForm> first = tengdaOrderFormList.stream().filter(tengdaForm -> tengdaForm.getUuid().equals(form.getUuid())).findFirst();
            if(first.isPresent()){
                CarOutPayForm outPayForm = JSONObject.toJavaObject(first.get().getDataItems().get(0), CarOutPayForm.class);

                //  开闸
                tengdaUtil.parkingRemote(form, outPayForm);

                //  删除缓存
                deleteCache(first.get());
            }
        }
    }

    /**
     * 出场预支付
     */
    @Override
    public void carOutPay(TengdaForm form) {
        log.info("出场预支付【{}】", form);
        CarOutPayForm outPayForm = JSONObject.toJavaObject(form.getDataItems().get(0), CarOutPayForm.class);
        log.info("出场预支付-业务数据【{}】", outPayForm);

        /*1、校验是否开闸*/
        Map<String, Object> carOutPayMap = BolianUtil.carOutPay(outPayForm.getRecordNo(), form.getParkCode(), outPayForm.getPlateNumber(), String.valueOf(outPayForm.getPaidFee()), DateTimeUtil.fomatDateTime(outPayForm.getEnterTime()), "15");

        JSONObject outPayParam = new JSONObject();
        if(carOutPayMap != null && carOutPayMap.get("state") != null && carOutPayMap.get("state").equals("1")){
            outPayParam.put("payStatus", 0);    //  0：无感支付 成功1：无感，异 步订单支付通 知2：未开通无 感/无感支付 失败
            //  支付通知
            tengdaUtil.payParkingFeeOrder(form, outPayForm);
        } else {
            outPayParam.put("payStatus", 2);    //  0：无感支付 成功1：无感，异 步订单支付通 知2：未开通无 感/无感支付 失败
        }
        outPayParam.put("recordNo", outPayForm.getRecordNo());
        outPayParam.put("plateID", outPayForm.getPlateID());
        outPayParam.put("vehicleStatus", 1);    //  0-非正常用户 1-正常用户
        List<Object> outPayDataItems = new ArrayList<>();
        outPayDataItems.add(outPayParam);

        JSONObject payBody = new JSONObject();
        payBody.put("code", 1);
        payBody.put("parkCode", form.getParkCode());
        payBody.put("serviceId", form.getServiceId());
        payBody.put("uuid", form.getUuid());
        payBody.put("dataItems", outPayDataItems);
        clientConfig.publish("tcp/" + form.getParkCode(), form.getServiceId(), payBody.toString());

        tengdaOrderFormList.add(form);
    }

    /**
     * 车辆出场通知
     */
    @Override
    public void carOutPark(TengdaForm form) throws InterruptedException {
        log.info("车辆出场通知【{}】", form);
        CarOutForm carOutForm = JSONObject.toJavaObject(form.getDataItems().get(0), CarOutForm.class);
        log.info("车辆出场通知-业务数据【{}】", carOutForm);

        carOutForm.setEnterTime(carOutForm.getEnterTime() == null ?  DateTimeUtil.convertYMDHMS(new Date()) : carOutForm.getEnterTime());
        carOutForm.setLeaveTime(carOutForm.getLeaveTime() == null ?  DateTimeUtil.convertYMDHMS(new Date()) : carOutForm.getLeaveTime());

        Long inTime = DateTimeUtil.fomatDateTime(carOutForm.getEnterTime()).getTime()/1000;  //符合泊链逻辑 精确到秒
        Long outTime = DateTimeUtil.fomatDateTime(carOutForm.getLeaveTime()).getTime()/1000; //符合泊链逻辑 精确到秒

        //  车牌
        CarDTO carDTO = carDao.getCustCarByCarNumber(carOutForm.getPlateNumber());
        //  停车场
        ParkInfoDTO parkInfoDTO = parkInfoDao.getByBolianParkId(form.getParkCode());
        //  客户id
        Long customerId = carDTO == null ? null : carDTO.getCustomerId();
        //  支付总金额（应付金额 减去 优惠金额）
        BigDecimal paidMoney = carOutForm.getPayableFee().subtract(carOutForm.getDiscountFee());
        if(carDTO != null) {
            //  通知泊链出场信息
            Boolean addFlag = BolianUtil.addOutParkOrder(form.getParkCode(), carOutForm.getPlateNumber(), inTime, outTime, carOutForm.getRecordNo(), carOutForm.getRemainParkNum(), String.valueOf(paidMoney));
            if(addFlag){
                Thread.sleep(8 * 1000);

                if(parkInfoDTO == null) {
                    log.error("停车场【{}】不存在", form.getParkCode());
                } else {
                    //  根据订单号查询订单
                    OrderInfoDTO orderInfoDTO = orderInfoDao.getByOrderCode(carOutForm.getRecordNo());
                    //  8秒后如果还没查询到订单，则手动入库
                    if(orderInfoDTO == null || orderInfoDTO.getStatus().equals(1)){
                        BolianUtil.carOutPark(carOutForm.getRecordNo(), form.getParkCode(), parkInfoDTO.getParkName(), carOutForm.getPlateNumber(), inTime, outTime, customerId, paidMoney);
                    }
                }
            }
        //  非会员车，不通知泊链
        } else {
            log.info("车牌【{}】非会员车，不上传泊链", carOutForm.getPlateNumber());
            //  根据订单号查询订单
            OrderInfoDTO orderInfoDTO = orderInfoDao.getByOrderCode(carOutForm.getRecordNo());
            //  8秒后如果还没查询到订单，则手动入库
            if(orderInfoDTO == null || orderInfoDTO.getStatus().equals(1)){
                BolianUtil.carOutPark(carOutForm.getRecordNo(), form.getParkCode(), parkInfoDTO.getParkName(), carOutForm.getPlateNumber(), inTime, outTime, customerId, paidMoney);
            }
        }
    }

    /**
     * 删除缓存
     */
    @Override
    @Async("threadPoolExecutor")
    public void deleteCache(TengdaForm form) {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //  删除缓存
        tengdaOrderFormList.remove(form);
    }

}
